home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / sun4.md / machCode.c < prev    next >
C/C++ Source or Header  |  1993-01-06  |  72KB  |  2,356 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *     C code for the mach module.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/sun4.md/machCode.c,v 9.42 93/01/06 20:09:15 mgbaker Exp $ SPRITE (Berkeley)";
  12. #endif /* not lint */
  13.  
  14. #include <stddef.h>
  15. #include <sprite.h>
  16. #include <swapBuffer.h>
  17. #include <machConst.h>
  18. #include <machMon.h>
  19. #include <machInt.h>
  20. #include <mach.h>
  21. #include <proc.h>
  22. #include <prof.h>
  23. #include <sys.h>
  24. #include <sched.h>
  25. #include <vm.h>
  26. #include <vmMach.h>
  27. #include <user/sun4.md/sys/machSignal.h>
  28. #include <procUnixStubs.h>
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <bstring.h>
  33. #include <compatInt.h>
  34. #include <ctype.h>
  35. #include <recov.h>
  36.  
  37. /*
  38.  *  Number of processors in the system.
  39.  */
  40. #ifndef NUM_PROCESSORS
  41. #define NUM_PROCESSORS 1
  42. #endif NUM_PROCESSORS
  43.  
  44. int mach_NumProcessors = NUM_PROCESSORS;
  45.  
  46. /*
  47.  * The following two variables should be in the initialized data space, but
  48.  * marked as not initialized.  Then, when they are updated as part of booting,
  49.  * their new values get preserved over a fast restart.
  50.  */
  51. int    storedDataSize = -1;
  52. char    *mach_RestartTablePtr = (char *) NIL;
  53.  
  54. /*
  55.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  56.  * user mode.
  57.  */
  58. Boolean    mach_KernelMode;
  59.  
  60. /*
  61.  * Sp saved into this before debugger call.
  62.  */
  63. int    machSavedRegisterState = 0;
  64.  
  65. /*
  66.  *  Flag used by routines to determine if they are running at
  67.  *  interrupt level.
  68.  */
  69. Boolean mach_AtInterruptLevel = FALSE;
  70.  
  71. /*
  72.  * The machine type string is imported by the file system and
  73.  * used when expanding $MACHINE in file names.
  74.  */
  75.  
  76. char *mach_MachineType = "sun4";
  77.  
  78. /*
  79.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data.
  80.  * For compatablity we set this to the old Swap_Buffer constant.
  81.  */
  82. Fmt_Format    mach_Format = FMT_SPARC_FORMAT;
  83.  
  84. /*
  85.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  86.  *  to disable interrupts.  Kept on a per-processor basis.
  87.  */
  88. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  89. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  90.  
  91. extern int debugProcStubs;
  92.  
  93. /*
  94.  * Machine dependent variables.
  95.  */
  96. Address    mach_KernStart;
  97. Address    mach_CodeStart;
  98. Address    mach_StackBottom;
  99. int    mach_KernStackSize;
  100. Address    mach_KernEnd;
  101. Address    mach_FirstUserAddr;
  102. Address    mach_LastUserAddr;
  103. Address    mach_MaxUserStackAddr;
  104. int    mach_LastUserStackPage;
  105.  
  106. Address    machTBRAddr;            /* address of trap table.  The value
  107.                      * is set up and stored here in
  108.                      * bootSysAsm.s.*/
  109. #define    MACH_NUM_VECTORS    256    /* Number of interrupt vector slots */
  110. Address    machVectorTable[MACH_NUM_VECTORS];    /* Table of autovector and
  111.                      * vectored interrupt handlers. */
  112. ClientData    machInterruptArgs[MACH_NUM_VECTORS];    /* Table of clientData
  113.                      * args to pass interrupt handlers */
  114. int    machMaxSysCall;            /* Hightest defined system call. */
  115. int    machArgOffsets[SYS_NUM_SYSCALLS];/* For each system call, tells how
  116.                      * much to add to the fp at the time
  117.                      * of the call to get to the highest
  118.                      * argument on the stack.  */
  119. Address    machArgDispatch[SYS_NUM_SYSCALLS];/* For each system call, gives an
  120.                      * address to branch to, in the
  121.                      * middle of MachFetchArgs, to copy the
  122.                      * right # of args from user space to
  123.                      * the kernel's stack. */
  124. ReturnStatus    (*(mach_NormalHandlers[SYS_NUM_SYSCALLS]))();
  125.                     /* For each system call, gives the
  126.                      * address of the routine to handle
  127.                      * the call for non-migrated processes.
  128.                          */
  129. ReturnStatus (*(mach_MigratedHandlers[SYS_NUM_SYSCALLS]))();
  130.                     /* For each system call, gives the
  131.                      * address of the routine to handle
  132.                          * the call for migrated processes. */
  133. int    machKcallTableOffset;        /* Byte offset of the kcallTable field
  134.                      * in a Proc_ControlBlock. */
  135. int    machStatePtrOffset;        /* Byte offset of the machStatePtr
  136.                      * field in a Proc_ControlBlock. */
  137. int    machSpecialHandlingOffset;    /* Byte offset of the specialHandling
  138.                      * field in a Proc_ControlBlock. */
  139. int    machTmpRegsOffset;        /* Offset of overflow temp regs. */
  140. int    machTmpRegsStore[2];        /* Temporary storage. */
  141. int    machGenFlagsOffset;        /* offset of genFlags field in a
  142.                      * Proc_ControlBlock. */
  143. int    machForeignFlag;        /* Value of PROC_FOREIGN available
  144.                      * in assembler. */
  145. int    MachPIDOffset;            /* Byte offset of pid in PCB */
  146. char    mach_DebugStack[0x2000];    /* The debugger stack. */
  147. unsigned int    machDebugStackStart;    /* Contains address of base of debugger
  148.                      * stack. */
  149. int    machSignalStackSizeOnStack;    /* size of mach module sig stack */
  150. int    machSigStackSize;        /* size of Sig_Stack structure */
  151. int    machSigStackOffsetOnStack;    /* offset of sigStack field in
  152.                      * MachSignalStack structure on the
  153.                      * the user stack. */
  154. int    machSigStackOffsetInMach;    /* offset to sigStack field in mach
  155.                      * state structure. */
  156. int    machSigContextSize;        /* size of Sig_Context structure */
  157. int    machSigContextOffsetOnStack;    /* offset of sigContext field in
  158.                      * MachSignalStack structure on the
  159.                      * user stack. */
  160. int    machSigContextOffsetInMach;    /* offset to sigContext field in mach
  161.                      * state structure. */
  162. int    machSigUserStateOffsetOnStack;    /* offset of machine-dependent field
  163.                      * on the stack, called machContext,
  164.                      * in the Sig_Context part of the
  165.                      * MachSignalStack structure. */
  166. int    machSigTrapInstOffsetOnStack;    /* offset of trapInst field in
  167.                      * MachSignalStack on user stack. */
  168. int    machSigNumOffsetInSig;        /* offset of sigNum field in
  169.                      * Sig_Stack structure. */
  170. int    machSigAddrOffsetInSig;        /* offset of sigAddr field in
  171.                      * Sig_Stack structure. */
  172. int    machSigCodeOffsetInSig;        /* offset of sigCode field in
  173.                      * Sig_Stack structure. */
  174. int    machSigPCOffsetOnStack;        /* offset of pcValue field in
  175.                      * MachSignalStack on user stack. */
  176. int    machLastSysCallOffset;        /* offset of lastSysCall field in
  177.                      * Mach_State structure. */
  178.  
  179.  
  180. Proc_ControlBlock *machFPUSaveProcPtr;    /* Set to the Proc_ControlBlock of the
  181.                      * process we are saving the FPU
  182.                      * state for in Mach_Context switch. */
  183. int        machFPUSyncInst();     /* PC of stfsr instruction in 
  184.                     * context switch. */
  185. int        machFPUDumpSyncInst(); /* PC of stfsr instruction in 
  186.                     * MachDumpFPUState. */
  187. /*
  188.  * Pointer to the state structure for the current process.
  189.  */
  190. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  191.  
  192. char    MachUnixAddr[] =
  193.                 "Unix addr %x\n"; 
  194. char    MachUnixString[] =
  195.                 "Unix syscall %d\n"; 
  196. char    MachUnixYesString[] =
  197.                 "syscall success\n"; 
  198. char    MachUnixNoString[] =
  199.                 "syscall failure\n"; 
  200. char    MachRunUserDeathString[] =
  201.                 "MachRunUserProc: killing process!\n"; 
  202. char    MachHandleSignalDeathString[] =
  203.                 "MachHandleSignal: killing process!\n"; 
  204. char    MachReturnFromSignalDeathString[] =
  205.                 "MachReturnFromSignal: killing process!\n"; 
  206. char    MachReturnFromTrapDeathString[] =
  207.                 "MachReturnFromTrap: killing process!\n"; 
  208. char    MachHandleWindowUnderflowDeathString[] =
  209.                 "MachHandleWindowUnderflow: killing process!\n";
  210.  
  211. /*
  212.  * For testing correctness of defined offsets.
  213.  */
  214. #if 0
  215. Mach_RegState        testMachRegState;
  216. Mach_State        testMachState;
  217. Proc_ControlBlock    testPCB;
  218. MachSignalStack        testSignalStack;
  219. Sig_Context        testContext;
  220. Sig_Stack        testStack;
  221. #endif
  222. int            debugCounter = 0;        /* for debugging */
  223. int            debugSpace[500];
  224. Address            theAddrOfVmPtr = 0; 
  225. Address            theAddrOfMachPtr = 0;
  226. Address            oldAddrOfVmPtr = 0; 
  227. Address            oldAddrOfMachPtr = 0;
  228.  
  229.                     /*
  230.                      * Make sure machRomVectorPtr is
  231.                      * in the initialized data section.
  232.                      * This is needed when transparent
  233.                      * recovery is used.
  234.                      */
  235. MachMonRomVector    *machRomVectorPtr = (MachMonRomVector *) NIL;
  236. MachMonBootParam    machMonBootParam;
  237. #ifdef sun4c
  238. unsigned char        *machInterruptReg;
  239. unsigned int        machClockRate;
  240. struct idprom        machIdProm = {0};
  241. #endif
  242.                     /*
  243.                      * Make sure these variables are
  244.                      * in the initialized data section.
  245.                      */
  246. unsigned int        machNumWindows = 0;
  247. unsigned int        machWimShift = 0;        /* # windows - 1 */
  248.  
  249. /*
  250.  * Forward declarations.
  251.  */
  252. static void FlushTheWindows _ARGS_((int num));
  253. static void HandleFPUException _ARGS_((Proc_ControlBlock *procPtr, 
  254.                        Mach_State *machStatePtr));
  255.  
  256. static void CheckFastRestart _ARGS_((void));
  257.  
  258.  
  259. /*
  260.  * ----------------------------------------------------------------------------
  261.  *
  262.  * Mach_Init --
  263.  *
  264.  *    Initialize some stuff.
  265.  *
  266.  * Results:
  267.  *    None.
  268.  *
  269.  * Side effects:
  270.  *    None.
  271.  *
  272.  * ----------------------------------------------------------------------------
  273.  */
  274. void
  275. Mach_Init()
  276. {
  277.     int        i;
  278.     extern    void    MachVectoredInterrupt();
  279.     extern    void    MachHandleDebugTrap();
  280.     int        offset;
  281.  
  282.     /*
  283.      * Set exported machine dependent variables.
  284.      */
  285.     mach_KernStart = (Address)MACH_KERN_START;
  286.     mach_KernEnd = (Address)MACH_KERN_END;
  287.     mach_CodeStart = (Address)MACH_CODE_START;
  288.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  289.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  290.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  291.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  292.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  293.     mach_LastUserStackPage = MACH_LAST_USER_STACK_PAGE;
  294.  
  295. #define    CHECK_SIZE(c, d)        \
  296.     if (sizeof (c) != d) {        \
  297.     panic("Bad size for structure.  Redo machConst.h!\n");\
  298.     }
  299.     
  300. #define    CHECK_OFFSETS(s, o)        \
  301.     if (offsetof(Mach_State, s) != o) { \
  302.     panic("Bad offset for registers.  Redo machConst.h!\n");\
  303.     }
  304. #define    CHECK_TRAP_REG_OFFSETS(s, o)       \
  305.     if (offsetof(Mach_RegState, s) != o) { \
  306.     panic("Bad offset for trap registers.  Redo machConst.h!\n");\
  307.     }
  308.  
  309.  
  310.     CHECK_SIZE(Mach_RegState, MACH_SAVED_STATE_FRAME);
  311.     CHECK_OFFSETS(trapRegs, MACH_TRAP_REGS_OFFSET);
  312.     CHECK_OFFSETS(switchRegs, MACH_SWITCH_REGS_OFFSET);
  313.     CHECK_OFFSETS(savedRegs[0][0], MACH_SAVED_REGS_OFFSET);
  314.     CHECK_OFFSETS(savedMask, MACH_SAVED_MASK_OFFSET);
  315.     CHECK_OFFSETS(savedSps[0], MACH_SAVED_SPS_OFFSET);
  316.     CHECK_OFFSETS(kernStackStart, MACH_KSP_OFFSET);
  317.     CHECK_OFFSETS(fpuStatus, MACH_FPU_STATUS_OFFSET)
  318.     CHECK_TRAP_REG_OFFSETS(curPsr, MACH_LOCALS_OFFSET);
  319.     CHECK_TRAP_REG_OFFSETS(ins[0], MACH_INS_OFFSET);
  320.     CHECK_TRAP_REG_OFFSETS(globals[0], MACH_GLOBALS_OFFSET);
  321.     CHECK_TRAP_REG_OFFSETS(fsr, MACH_FPU_FSR_OFFSET);
  322.     CHECK_TRAP_REG_OFFSETS(numQueueEntries, MACH_FPU_QUEUE_COUNT);
  323.     CHECK_TRAP_REG_OFFSETS(fregs[0], MACH_FPU_REGS_OFFSET);
  324.     CHECK_TRAP_REG_OFFSETS(fqueue[0], MACH_FPU_QUEUE_OFFSET);
  325.  
  326. #ifdef sun4c
  327.     if (romVectorPtr->v_romvec_version < 2) {
  328.     if ((*(romVectorPtr->virtMemory))->address !=
  329.         (unsigned) VMMACH_DEV_START_ADDR ||
  330.         ((unsigned) VMMACH_DEV_START_ADDR +
  331.         (*(romVectorPtr->virtMemory))->size - 1)
  332.         != (unsigned) VMMACH_DEV_END_ADDR) {
  333.         panic("VMMACH_DEV_START_ADDR and VMMACH_DEV_END_ADDR are wrong.\n");
  334.     }
  335.     }
  336. #endif /* sun4c */
  337. #undef CHECK_SIZE
  338. #undef CHECK_OFFSETS
  339.     /*
  340.      * Initialize some of the dispatching information.  The rest is initialized
  341.      * by Mach_InitSysCall, below.
  342.      */
  343.  
  344.     /*
  345.      * Get offset of machStatePtr in proc control blocks.  This one is
  346.      * subject to a different module, so it's easier not to use a constant.
  347.      */
  348.     machStatePtrOffset = offsetof(Proc_ControlBlock, machStatePtr);
  349.     machKcallTableOffset = offsetof(Proc_ControlBlock, kcallTable);
  350.     machSpecialHandlingOffset = offsetof(Proc_ControlBlock, specialHandling);
  351.  
  352.     if (MACH_UNIX_ERRNO_OFFSET != offsetof(Proc_ControlBlock, unixErrno)) {
  353.     panic("MACH_UNIX_ERRNO_OFFSET is wrong!\n");
  354.     }
  355.  
  356.     machMaxSysCall = -1;
  357.     MachPIDOffset = offsetof(Proc_ControlBlock, processID);
  358.     machGenFlagsOffset = offsetof(Proc_ControlBlock, genFlags);
  359.     machForeignFlag = PROC_FOREIGN;
  360.  
  361.     /*
  362.      * Initialize all the horrid offsets for dealing with getting stuff from
  363.      * signal things in the mach state structure to signal things on the user
  364.      * stack.
  365.      */
  366.     machSignalStackSizeOnStack = sizeof (MachSignalStack);
  367.     if ((machSignalStackSizeOnStack & 0x7) != 0) {
  368.     panic("MachSignalStack struct must be a multiple of double-words!\n");
  369.     }
  370.  
  371.     machSigStackSize = sizeof (Sig_Stack);
  372.     machSigStackOffsetOnStack = offsetof(MachSignalStack, sigStack);
  373.     machSigStackOffsetInMach = offsetof(Mach_State, sigStack);  
  374.     machSigContextSize = sizeof (Sig_Context);
  375.     machSigContextOffsetOnStack = offsetof(MachSignalStack, sigContext);
  376.     machSigContextOffsetInMach = offsetof(Mach_State, sigContext);
  377.     machSigUserStateOffsetOnStack = offsetof(MachSignalStack, 
  378.         sigContext.machContext.userState);
  379.     machSigTrapInstOffsetOnStack = offsetof(MachSignalStack,
  380.         sigContext.machContext.trapInst);
  381.     machSigNumOffsetInSig = offsetof(Sig_Stack, sigNum);
  382.     machSigAddrOffsetInSig = offsetof(Sig_Stack, sigAddr);
  383.     machSigCodeOffsetInSig = offsetof(Sig_Stack, sigCode);
  384.     machSigPCOffsetOnStack = offsetof(MachSignalStack, 
  385.         sigContext.machContext.pcValue);
  386.  
  387.     machLastSysCallOffset = offsetof(Mach_State, lastSysCall);
  388.  
  389.     /*
  390.      * base of the debugger stack
  391.      */
  392.     machDebugStackStart = (unsigned int) mach_DebugStack +
  393.                         sizeof (mach_DebugStack);
  394.  
  395.     /*
  396.      * Initialize the interrupt vector table.
  397.      */
  398.     for (i = 0; i < MACH_NUM_VECTORS; i++) {
  399. #ifndef sun4c
  400.     if (i == 13 || i == 11 || i == 9 || i == 7 || i == 5 || i == 3 ||
  401.         i == 2) {
  402.         machVectorTable[i] = (Address) MachVectoredInterrupt;
  403.         /*
  404.          * Set arg to vme vector address for this trap level.
  405.          * In the high bits of the address, we want MACH_VME_INTR_VECTOR.
  406.          * In bits 3 to 1 we want the VME bus level.  We want bit 0 to be
  407.          * 1.  So, for example, for interrupt level 13, we want to put
  408.          * VME level7 into bits 3 to 1 and then set bit 0 high.  But this
  409.          * is equivalent to putting the number 14 into bits 3 to 0 and then
  410.          * setting bit 0 high.  So this means adding 1 to the interrupt
  411.          * level and then setting bit 0 high.
  412.          */
  413.         machInterruptArgs[i] = (ClientData)
  414.             (MACH_VME_INTR_VECTOR | ((i + 1) | 1));
  415.     } else { 
  416. #endif
  417.         machVectorTable[i] = (Address) MachHandleDebugTrap;
  418.         machInterruptArgs[i] = (ClientData) 0;
  419. #ifndef sun4c
  420.     }
  421. #endif
  422.     }
  423.  
  424.     /* Temporary: for debugging net module and debugger: */
  425.     mach_NumDisableInterrupts[0] = 1;
  426.  
  427. #ifdef sun4c
  428.     if (romVectorPtr->v_romvec_version < 2) {
  429. #endif
  430.     /*
  431.      * Copy the boot parameter structure. The original location will get
  432.      * unmapped during vm initialization so we need to get our own copy.
  433.      */
  434.     machMonBootParam = **(romVectorPtr->bootParam);
  435.     offset = (unsigned int) *(romVectorPtr->bootParam) - 
  436.          (unsigned int) &(machMonBootParam);
  437.     for (i = 0; i < 8; i++) {
  438.         if (machMonBootParam.argPtr[i] != (char *) 0 &&
  439.          machMonBootParam.argPtr[i] != (char *) NIL) {
  440.         machMonBootParam.argPtr[i] -= offset;
  441.         }
  442.     }
  443. #ifdef sun4c
  444.     } 
  445. #endif
  446. #ifndef sun4c
  447.     /*
  448.      * Clear out the line input buffer to the prom so we don't get extra
  449.      * characters at the end of shorter reboot strings.
  450.      */
  451.     bzero((char *)(romVectorPtr->lineBuf), *romVectorPtr->lineSize);
  452. #endif
  453.  
  454. #ifdef sun4c
  455.     if (Mach_MonSearchProm("*", "clock-frequency",
  456.         (char *)&machClockRate,
  457.         sizeof machClockRate) != sizeof machClockRate) {
  458.     panic("Clock rate not found.\n");
  459.     }
  460.     /*
  461.      * Keep clock rate precision to 1 decimal place.
  462.      */
  463.     machClockRate /= 100000;
  464. #ifdef NOTDEF        /* No need to print this stuff. */
  465.     Mach_MonPrintf("PROM: Clock rate is %d.%dMHz\n",
  466.     machClockRate / 10, machClockRate % 10);
  467. #endif /* NOTDEF */
  468.  
  469.     if (Mach_MonSearchProm("interrupt-enable", "address",
  470.         (char *)&machInterruptReg,
  471.         sizeof machInterruptReg) != sizeof machInterruptReg) {
  472.     panic("Interrupt register not found.\n");
  473.     }
  474. #ifdef NOTDEF        /* No need to print this stuff. */
  475.     Mach_MonPrintf("PROM: Interrupt register is at %x\n", machInterruptReg);
  476. #endif /* NOTDEF */
  477.  
  478.     /*
  479.      * This gets turned on by the profiler init when it is called.
  480.      */
  481.     *Mach_InterruptReg &= ~MACH_ENABLE_LEVEL14_INTR;
  482. #endif
  483.     
  484.     if (recov_Transparent) {
  485.     CheckFastRestart();
  486.     }
  487.  
  488.     return;
  489. }
  490.  
  491.  
  492. /*
  493.  *----------------------------------------------------------------------
  494.  *
  495.  * CheckFastRestart --
  496.  *
  497.  *    Check if enough space was allocated for the fast restart.
  498.  *
  499.  * Results:
  500.  *    None.
  501.  *
  502.  * Side effects:
  503.  *    None.
  504.  *
  505.  *----------------------------------------------------------------------
  506.  */
  507. static void
  508. CheckFastRestart()
  509. {
  510.     char    *src, *dest;
  511.     int        count;
  512.     extern    int    edata;
  513.     extern    int    etext();
  514.  
  515.     src =  (char *) &etext;
  516.     dest = (char *) &edata;
  517.     count = (unsigned int) dest - (unsigned int) src;
  518.     if (count > MACH_RESTART_DATA_SIZE) {
  519.     Mach_MonPrintf("Not enough restart space saved for kernel data.\n");
  520.     Mach_MonAbort();
  521.     }
  522.  
  523.     return;
  524. }
  525.  
  526.  
  527. /*
  528.  *----------------------------------------------------------------------
  529.  *
  530.  * Mach_GetRestartTableSize --
  531.  *
  532.  *    Return the size allocated for the fast restart table area.
  533.  *
  534.  * Results:
  535.  *    None.
  536.  *
  537.  * Side effects:
  538.  *    None.
  539.  *
  540.  *----------------------------------------------------------------------
  541.  */
  542. int
  543. Mach_GetRestartTableSize()
  544. {
  545.     return MACH_RESTART_TABLE_SIZE;
  546. }
  547.  
  548.  
  549. /*
  550.  *----------------------------------------------------------------------
  551.  *
  552.  * Mach_InitFirstProc --
  553.  *
  554.  *    Initialize the machine state struct for the very first process.
  555.  *
  556.  * Results:
  557.  *    None.
  558.  *
  559.  * Side effects:
  560.  *    Machine info allocated and stack start set up.
  561.  *
  562.  *----------------------------------------------------------------------
  563.  */
  564. void
  565. Mach_InitFirstProc(procPtr)
  566.     Proc_ControlBlock    *procPtr;
  567. {
  568.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  569.     bzero((char *)(procPtr->machStatePtr), sizeof (Mach_State));
  570.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  571.     procPtr->machStatePtr->trapRegs = (Mach_RegState *) NIL;
  572.     procPtr->machStatePtr->switchRegs = (Mach_RegState *) NIL;
  573.     machCurStatePtr = procPtr->machStatePtr;
  574. }
  575.  
  576.  
  577. /*
  578.  *----------------------------------------------------------------------
  579.  *
  580.  * Mach_SetupNewState --
  581.  *
  582.  *    Initialize the machine state for this process.  This includes 
  583.  *    allocating and initializing a kernel stack.  Assumed that will
  584.  *    be called when starting a process after a fork or restarting a
  585.  *    process after a migration.
  586.  *
  587.  * Results:
  588.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  589.  *
  590.  * Side effects:
  591.  *    Machine state in the destination process control block is overwritten.
  592.  *
  593.  *----------------------------------------------------------------------
  594.  */ 
  595. ReturnStatus
  596. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  597.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  598.                      * to initialize state for. */
  599.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  600.                      * other machine on migration. */
  601.     void        (*startFunc)();    /* Function to call when process first
  602.                      * starts executing. */
  603.     Address        startPC;    /* Address to pass as argument to 
  604.                      * startFunc.  If NIL then the address
  605.                      * is taken from *fromStatePtr's 
  606.                      * exception stack. */
  607.     Boolean        user;        /* TRUE if is a user process. */
  608. {
  609.     register    Mach_RegState    *stackPtr;
  610.     register    Mach_State    *statePtr;
  611.  
  612.     /*
  613.      * If it's a user process forking, we must make sure all its windows have
  614.      * been saved to the stack so that when the register state and the stack
  615.      * are copied to the new process, it will get the real stuff.
  616.      */
  617.     if (user) {
  618.     Mach_DisableIntr();
  619.     Mach_FlushWindowsToStack();
  620.     Mach_EnableIntr();
  621.     }
  622.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  623.     procPtr->machStatePtr = (Mach_State *)Vm_RawAlloc(sizeof(Mach_State));
  624.     }
  625.     bzero((char *) procPtr->machStatePtr, sizeof (Mach_State));
  626.     statePtr = procPtr->machStatePtr;
  627.     statePtr->trapRegs = (Mach_RegState *)NIL;
  628.     /* 
  629.      * Allocate a kernel stack for this process.
  630.      */
  631.     statePtr->kernStackStart = (Address) Vm_GetKernelStack(0);
  632.     if (statePtr->kernStackStart == (Address)NIL) {
  633.     return(PROC_NO_STACKS);
  634.     }
  635.  
  636.     /*
  637.      * Pointer to context switch register's save area is also a pointer
  638.      * to the top of the stack, since the regs are saved there.
  639.      * If this is a kernel process, we only need space MACH_SAVED_STATE_FRAME
  640.      * + MACH_FULL_STACK_FRAME, but if it's a user process we need more:
  641.      * (2 * MACH_SAVED_STATE_FRAME).  Both types of processes need the
  642.      * first MACH_SAVED_STATE_FRAME for their context switch regs area.  A
  643.      * kernel process then only needs space under that on its stack for its
  644.      * first routine to store its arguments in its "caller's" stack frame, so
  645.      * this extra space just fakes a caller's stack frame.  But for a user
  646.      * process, we have trap regs.  And these trapRegs get stored under
  647.      * the context switch regs on the kernel stack.
  648.      */
  649.     statePtr->switchRegs = (Mach_RegState *)((statePtr->kernStackStart) +
  650.         MACH_KERN_STACK_SIZE - (2 * MACH_SAVED_STATE_FRAME));
  651.     statePtr->switchRegs = (Mach_RegState *)
  652.     (((unsigned int)(statePtr->switchRegs)) & ~0x7);  /* should be okay already */
  653.     /*
  654.      * Initialize the stack so that it looks like it is in the middle of
  655.      * Mach_ContextSwitch.
  656.      */
  657.     stackPtr = statePtr->switchRegs;    /* stack pointer is set from this. */
  658.     /*
  659.      * Fp is set to saved window area for window we'll return to.  The area for
  660.      * the window of Mach_ContextSwitch is a Mach_RegState.  Below this on
  661.      * the stack (at higher address than) is the saved window area of the
  662.      * routine we'll return to from Mach_ContextSwitch.  So the fp must be
  663.      * set to the top of this saved window area.
  664.      */
  665.     *((Address *)(((Address)stackPtr) + MACH_FP_OFFSET)) =
  666.         ((Address)stackPtr) + MACH_SAVED_STATE_FRAME;
  667.     /*
  668.      * We are to return to startFunc from Mach_ContextSwitch, but
  669.      * Mach_ContextSwitch will do a return to retPC + 8, so we subtract
  670.      * 8 from it here to get to the right place.
  671.      */
  672.     *((Address *)(((Address)stackPtr) + MACH_RETPC_OFFSET)) =
  673.         ((Address)startFunc) - 8;
  674.  
  675.     /*
  676.      * Set the psr to restore to have traps enabled and interrupts off.
  677.      */
  678.     stackPtr->curPsr = MACH_HIGH_PRIO_PSR;
  679.     /* 
  680.      * Set up the state of the process.  User processes inherit from their
  681.      * parent or the migrated process.  If the PC is not specified, take it
  682.      * from the parent as well.
  683.      */
  684.     if (user) {
  685.     /*
  686.      * Trap state regs are the same for child process.
  687.      */
  688.     statePtr->trapRegs = (Mach_RegState *)
  689.         (((Address) stackPtr) + MACH_SAVED_STATE_FRAME);
  690.     bcopy((Address)fromStatePtr->trapRegs, (Address)statePtr->trapRegs,
  691.         sizeof (Mach_RegState));
  692.     /*
  693.      * Check to see if any register windows were saved to internal buffer
  694.      * in Mach_FlushWindowsToStack(), above.  If so, copy the buffer state
  695.      * to the new process, so that when it returns from the fork trap, it
  696.      * will copy out the saved windows to its stack.
  697.      */
  698.     if (fromStatePtr->savedMask != 0) {
  699.         procPtr->specialHandling = 1;
  700.         statePtr->savedMask = fromStatePtr->savedMask;
  701.         bcopy((Address) fromStatePtr->savedRegs,
  702.             (Address) statePtr->savedRegs,
  703.             sizeof (fromStatePtr->savedRegs));
  704.         bcopy((Address) fromStatePtr->savedSps,
  705.             (Address) statePtr->savedSps,
  706.             sizeof (fromStatePtr->savedSps));
  707.     }
  708.     }
  709.     if (startPC == (Address)NIL) {
  710.     *((Address *)(((Address)stackPtr) + MACH_ARG0_OFFSET)) =
  711.         (Address) fromStatePtr->trapRegs->pc;
  712.     } else {
  713.     /*
  714.      * The first argument to startFunc is supposed to be startPC.  But that
  715.      * would be in an in register in startFunc's window which is one before
  716.      * Mach_ContextSwitch's window.  But startFunc will do a save operation
  717.      * at the beginning so it will actually be executing in Mach_ContextS's
  718.      * window, so arg0 to startFunc must actually be arg0 that is restored
  719.      * at the end of Mach_ContextSwitch, so we have to put it in the in
  720.      * register area of Mach_RegState area on the stack.  Weird.
  721.      */
  722.     *((Address *)(((Address)stackPtr) + MACH_ARG0_OFFSET)) = startPC;
  723.     }
  724.     return(SUCCESS);
  725. }
  726.  
  727. /*
  728.  *----------------------------------------------------------------------
  729.  *
  730.  * Mach_SetReturnVal --
  731.  *
  732.  *    Set the return value for a process from a system call.  Intended to
  733.  *    be called by the routine that starts a user process after a fork.
  734.  *    Interrupts must be off here!
  735.  *
  736.  * Results:
  737.  *    None.
  738.  *
  739.  * Side effects:
  740.  *    Register D0 is set in the user registers.
  741.  *
  742.  *----------------------------------------------------------------------
  743.  */ 
  744. void
  745. Mach_SetReturnVal(procPtr, retVal, retVal2)
  746.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  747.     int            retVal;        /* Value for process to return. */
  748.     int            retVal2;    /* 2nd Value for process to return. */
  749. {
  750.     if (procPtr->machStatePtr->trapRegs == (Mach_RegState *) NIL ||
  751.         procPtr->machStatePtr->trapRegs == (Mach_RegState *) 0) {
  752.     return;
  753.     }
  754.     procPtr->machStatePtr->trapRegs->ins[0] = retVal;
  755.     procPtr->machStatePtr->trapRegs->ins[1] = retVal2;
  756.     return;
  757. }
  758.  
  759.  
  760. /*
  761.  *----------------------------------------------------------------------
  762.  *
  763.  * Mach_StartUserProc --
  764.  *
  765.  *    Start a user process executing for the first time.
  766.  *    Interrupts must be off here!
  767.  *
  768.  * Results:
  769.  *    None.
  770.  *
  771.  * Side effects:
  772.  *    Stack pointer and the program counter set for the process and
  773.  *    the current process's image is replaced.
  774.  *
  775.  *----------------------------------------------------------------------
  776.  */
  777. void
  778. Mach_StartUserProc(procPtr, entryPoint)
  779.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  780.                      * to start. */
  781.     Address        entryPoint;    /* Where process is to start
  782.                      * executing. */
  783. {
  784.     register    Mach_State    *statePtr;
  785.  
  786.     statePtr = procPtr->machStatePtr;
  787.     /*
  788.      * MachRunUserProc will put the values from our trap regs into the actual
  789.      * registers so that we'll be in shape to rett back to user mode.
  790.      */
  791.     Mach_DisableIntr();
  792.  
  793.     /*
  794.      * Return from trap pc.
  795.      */
  796.     statePtr->trapRegs->pc = (unsigned int) entryPoint;
  797.     statePtr->trapRegs->nextPc = (unsigned int) (entryPoint + 4);
  798.  
  799.     MachRunUserProc();
  800.     /* THIS DOES NOT RETURN */
  801. }
  802.  
  803.  
  804. /*
  805.  *----------------------------------------------------------------------
  806.  *
  807.  * Mach_ExecUserProc --
  808.  *
  809.  *    Replace the calling user process's image with a new one.
  810.  *
  811.  * Results:
  812.  *    None.
  813.  *
  814.  * Side effects:
  815.  *    Stack pointer set for the process.
  816.  *
  817.  *----------------------------------------------------------------------
  818.  */
  819. void
  820. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  821.     Proc_ControlBlock    *procPtr;        /* Process control block for
  822.                          * process to exec. */
  823.     Address        userStackPtr;        /* Stack pointer for when the
  824.                          * user process resumes 
  825.                          * execution. */
  826.     Address        entryPoint;        /* Where the user process is
  827.                          * to resume execution. */
  828. {
  829.     Mach_RegState    tmpTrapState;
  830.  
  831.      /*
  832.       * We do not call DISABLE_INTR here because there's an implicit enable
  833.       * of interrupts in MachRunUserProc().
  834.       */
  835.     Mach_DisableIntr();
  836.     machCurStatePtr = procPtr->machStatePtr;
  837.     /*
  838.      * Since we're not returning, we can just use this space on our kernel
  839.      * stack as trapRegs.  This is safe, since we only fill in the fp, tbr,
  840.      * pc, and nextPc fields (in Mach_StartUserProc()) and these just touch
  841.      * the saved-window section of our stack and won't mess up any of our
  842.      * arguments.
  843.      */
  844.     procPtr->machStatePtr->trapRegs = &tmpTrapState;
  845.     /*
  846.      * The user stack pointer gets MACH_FULL_STACK_FRAME subtracted from it
  847.      * so that the user stack has space for its first routine to store its
  848.      * arguments in its caller's stack frame.  (So we create a fake caller's
  849.      * stack frame this way.)
  850.      */
  851.     procPtr->machStatePtr->trapRegs->ins[MACH_FP_REG] = (unsigned int)
  852.         (userStackPtr - MACH_FULL_STACK_FRAME);
  853.     procPtr->machStatePtr->trapRegs->curPsr = MACH_FIRST_USER_PSR;
  854.     procPtr->machStatePtr->trapRegs->pc = (unsigned int) entryPoint;
  855.     procPtr->machStatePtr->trapRegs->tbr = (unsigned int) machTBRAddr;
  856.     /*
  857.      * Initialized the floating point state.
  858.      */
  859.     procPtr->machStatePtr->fpuStatus = 0;
  860.     /*
  861.      * Return value is cleared for exec'ing user process.  This shouldn't
  862.      * matter since a good exec won't return.
  863.      */
  864.     procPtr->machStatePtr->trapRegs->ins[0] = 0;
  865.     Mach_StartUserProc(procPtr, entryPoint);
  866.     /* THIS DOES NOT RETURN */
  867. }
  868.  
  869. /*
  870.  *----------------------------------------------------------------------
  871.  *
  872.  * Mach_FreeState --
  873.  *
  874.  *    Free up the machine state for the given process control block.
  875.  *
  876.  * Results:
  877.  *    None.
  878.  *
  879.  * Side effects:
  880.  *    Free up the kernel stack.
  881.  *
  882.  *----------------------------------------------------------------------
  883.  */
  884. void
  885. Mach_FreeState(procPtr)
  886.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  887.                      * machine state for. */
  888. {
  889.  
  890.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  891.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  892.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  893.     }
  894. }
  895.  
  896.  
  897. /*
  898.  *----------------------------------------------------------------------
  899.  *
  900.  * Mach_GetDebugState --
  901.  *
  902.  *    Extract the appropriate fields from the machine state struct
  903.  *    and store them into the debug struct.
  904.  *
  905.  * Results:
  906.  *    None.
  907.  *
  908.  * Side effects:
  909.  *    Debug struct filled in from machine state struct.
  910.  *
  911.  *----------------------------------------------------------------------
  912.  */ 
  913. void
  914. Mach_GetDebugState(procPtr, debugStatePtr)
  915.     Proc_ControlBlock    *procPtr;
  916.     Proc_DebugState    *debugStatePtr;
  917. {
  918.     register    Mach_State    *machStatePtr;
  919.  
  920.     machStatePtr = procPtr->machStatePtr;
  921.     bcopy((Address)machStatePtr->trapRegs,
  922.           (Address)(&debugStatePtr->regState), sizeof(Mach_DebugState));
  923.     return;
  924. }
  925.  
  926.  
  927. /*
  928.  *----------------------------------------------------------------------
  929.  *
  930.  * Mach_SetDebugState --
  931.  *
  932.  *    Extract the appropriate fields from the debug struct
  933.  *    and store them into the machine state struct.
  934.  *
  935.  * Results:
  936.  *    None.
  937.  *
  938.  * Side effects:
  939.  *    Machine state struct filled in from the debug state struct.
  940.  *
  941.  *----------------------------------------------------------------------
  942.  */ 
  943. void
  944. Mach_SetDebugState(procPtr, debugStatePtr)
  945.     Proc_ControlBlock    *procPtr;
  946.     Proc_DebugState    *debugStatePtr;
  947. {
  948.     register    Mach_State    *machStatePtr;
  949.  
  950. /* y, pc's g1-g7 all in's*/
  951.     machStatePtr = procPtr->machStatePtr;
  952.     machStatePtr->trapRegs->pc = debugStatePtr->regState.pc;
  953.     machStatePtr->trapRegs->nextPc = debugStatePtr->regState.nextPc;
  954.     machStatePtr->trapRegs->y = debugStatePtr->regState.y;
  955.     bcopy((Address)debugStatePtr->regState.ins,
  956.         (Address)machStatePtr->trapRegs->ins, MACH_NUM_INS * sizeof (int));
  957.     bcopy((Address)debugStatePtr->regState.globals,
  958.         (Address)machStatePtr->trapRegs->globals,
  959.         MACH_NUM_GLOBALS * sizeof (int));
  960.     return;
  961. }
  962.  
  963.  
  964. /*
  965.  *----------------------------------------------------------------------
  966.  *
  967.  * Mach_InitSyscall --
  968.  *
  969.  *    During initialization, this procedure is called once for each
  970.  *    kernel call, in order to set up information used to dispatch
  971.  *    the kernel call.  This procedure must be called once for each
  972.  *    kernel call, in order starting at 0.
  973.  *
  974.  * Results:
  975.  *    None.
  976.  *
  977.  * Side effects:
  978.  *    Initializes the dispatch tables for the kernel call.
  979.  *
  980.  *----------------------------------------------------------------------
  981.  */
  982. void
  983. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  984.     int callNum;            /* Number of the system call. */
  985.     int numArgs;            /* Number of one-word arguments passed
  986.                      * into call on stack. */
  987.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  988.                      * when process isn't migrated. */
  989.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  990.                      * for migrated processes. */
  991. {
  992.     machMaxSysCall++;
  993.     if (machMaxSysCall != callNum) {
  994.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  995.            callNum);
  996.     }
  997.     if (machMaxSysCall >= SYS_NUM_SYSCALLS) {
  998.     printf("Warning: too many kernel calls.\n");
  999.     machMaxSysCall--;
  1000.     return;
  1001.     }
  1002.     if (numArgs > SYS_MAX_ARGS) {
  1003.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  1004.     numArgs = SYS_MAX_ARGS;
  1005.     }
  1006.     /*
  1007.      * Offset of beginning of args on stack - offset from frame pointer.
  1008.      * Figure out offset  from fp of params past the sixth.
  1009.      * It copies from last arg to first
  1010.      * arg in that order, so we start offset at bottom of last arg.
  1011.      */
  1012.     /*
  1013.      * TURN THESE INTO PROPER CONSTANTS!
  1014.      */
  1015.     /*
  1016.      * We copy going towards higher addresses, rather than lower, as the sun3
  1017.      * does it.  So our offset is at top of extra parameters to copy, and not
  1018.      * below them (stack-wise speaking, not address-wise speaking).
  1019.      */
  1020.     machArgOffsets[machMaxSysCall] = MACH_SAVED_WINDOW_SIZE +
  1021.         MACH_ACTUAL_HIDDEN_AND_INPUT_STORAGE;
  1022.     
  1023.     /*
  1024.      * Where to jump to in fetching routine to copy the right amount from
  1025.      * the stack.  The fewer args we have, the farther we jump...  Figure out
  1026.      * how many are in registers, then do rest from stack.  There's instructions
  1027.      * to copy 10 words worth, for now, since 6 words worth of arguments are
  1028.      * in the input registers.  If this number changes, change machTrap.s
  1029.      * and the jump offset below!
  1030.      */
  1031.     if (numArgs <= 6) {
  1032.     machArgDispatch[machMaxSysCall] =  (Address) MachFetchArgsEnd;
  1033.     } else {
  1034.     machArgDispatch[machMaxSysCall] = (10 - (numArgs - 6))*16 +
  1035.         ((Address)MachFetchArgs);
  1036.     }
  1037.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  1038.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  1039. }
  1040.  
  1041.  
  1042. /*
  1043.  * ----------------------------------------------------------------------------
  1044.  *
  1045.  * Mach_SetHandler --
  1046.  *
  1047.  *    This is used both for autovectored devices and for regular interrupt
  1048.  *    routines for device interrupt levels.  For autovectored devices,
  1049.  *    the routine MachVectoredInterrupt will already have been installed
  1050.  *    for the auto-vectored interrupt levels.  Then this routine should be
  1051.  *    be called with the interrrupt vector for the device and its
  1052.  *    real interrupt handler.  For non-autovectored interrupt handlers, the
  1053.  *    handler should just be installed with a vector that is the
  1054.  *    device's interrupt level.
  1055.  *
  1056.  * Results:
  1057.  *     None.
  1058.  *
  1059.  * Side effects:
  1060.  *     The exception vector table is modified.
  1061.  *
  1062.  * ----------------------------------------------------------------------------
  1063.  */
  1064. void
  1065. Mach_SetHandler(vectorNumber, handler, clientData)
  1066.     int vectorNumber;        /* Vector number that the device generates */
  1067.     int (*handler)();        /* Interrupt handling procedure */
  1068.     ClientData    clientData;    /* ClientData for interrupt callback routine. */
  1069. {
  1070.  
  1071.     if (vectorNumber < 0 || vectorNumber > 255) {
  1072.     panic("Warning: Bad vector number %d\n", vectorNumber);
  1073.     } else {
  1074.     machVectorTable[vectorNumber] = (Address) handler;
  1075.     machInterruptArgs[vectorNumber] = (ClientData) clientData;
  1076.     }
  1077. }
  1078.  
  1079.  
  1080. /*
  1081.  * ----------------------------------------------------------------------------
  1082.  *
  1083.  * Routines to set up and return from signal handlers.
  1084.  *
  1085.  * In order to call a handler four things must be done:
  1086.  *
  1087.  *    1) The current state of the process must be saved so that when
  1088.  *       the handler returns a normal return to user space can occur.
  1089.  *    2) The user stack must be set up so that the signal number and the
  1090.  *       the signal code are passed to the handler.
  1091.  *    3) Things must be set up so that when the handler returns it returns
  1092.  *       back into the kernel so that state can be cleaned up.
  1093.  *    4) The trap stack that was created when the kernel was entered and is
  1094.  *       used to return a process to user space must be modified so that
  1095.  *       the signal handler is called instead of executing the
  1096.  *       normal return.
  1097.  *
  1098.  * The last one is done by simply changing the program counter where the
  1099.  * user process will execute on return to be the address of the signal
  1100.  * handler and the user stack pointer to point to the proper place on
  1101.  * the user stack.  The first three of these are accomplished by 
  1102.  * setting up the user stack properly.  The top entry on the stack is the
  1103.  * return address where the handler will start executing upon return.  But 
  1104.  * this is just the address of a trap instruction that is stored on the stack
  1105.  * below.  Thus when a handler returns it will execute a trap instruction 
  1106.  * and drop back into the kernel. 
  1107.  */
  1108.  
  1109.  
  1110. /*
  1111.  * ----------------------------------------------------------------------------
  1112.  *
  1113.  * MachCallSigReturn --
  1114.  *
  1115.  *      Process a return from a signal handler.  Call the Sig_Return
  1116.  *    routine with appropriate args.
  1117.  *    
  1118.  * Results:
  1119.  *      None.
  1120.  *
  1121.  * Side effects:
  1122.  *    Whatever Sig_Return does.
  1123.  *
  1124.  * ----------------------------------------------------------------------------
  1125.  */
  1126. void
  1127. MachCallSigReturn()
  1128. {
  1129.     Proc_ControlBlock    *procPtr;
  1130.     Mach_State        *statePtr;
  1131.     Sig_Stack        *sigStackPtr;
  1132.  
  1133.     procPtr = Proc_GetCurrentProc();
  1134.     statePtr = procPtr->machStatePtr;
  1135.  
  1136.     sigStackPtr = &(statePtr->sigStack);
  1137.     sigStackPtr->contextPtr = &(statePtr->sigContext);
  1138.  
  1139.     /*
  1140.      * Take the proper action on return from a signal.
  1141.      */
  1142.     Sig_Return(procPtr, sigStackPtr);
  1143. }
  1144.  
  1145.  
  1146. /*
  1147.  * ----------------------------------------------------------------------------
  1148.  *
  1149.  * Mach_ProcessorState --
  1150.  *
  1151.  *    Determines what state the processor is in.
  1152.  *
  1153.  * Results:
  1154.  *    MACH_USER    if was at user level
  1155.  *    MACH_KERNEL    if was at kernel level
  1156.  *
  1157.  * Side effects:
  1158.  *    None.
  1159.  *
  1160.  * ----------------------------------------------------------------------------
  1161.  */
  1162. /*ARGSUSED*/
  1163. Mach_ProcessorStates 
  1164. Mach_ProcessorState(processor)
  1165.     int processor;    /* processor number for which info is requested */
  1166. {
  1167.     if (mach_KernelMode) {
  1168.     return(MACH_KERNEL);
  1169.     } else {
  1170.     return(MACH_USER);
  1171.     }
  1172. }
  1173.  
  1174.  
  1175. /*
  1176.  * ----------------------------------------------------------------------------
  1177.  *
  1178.  * Mach_GetMachineArch --
  1179.  *
  1180.  *    Return the machine architecture (SYS_SUN2 or SYS_SUN3).
  1181.  *
  1182.  * Results:
  1183.  *    The machine architecture.
  1184.  *
  1185.  * Side effects:
  1186.  *    None.
  1187.  *
  1188.  * ----------------------------------------------------------------------------
  1189.  */
  1190. int
  1191. Mach_GetMachineArch()
  1192. {
  1193. #       ifdef sun2
  1194.     return SYS_SUN2;
  1195. #       endif sun2
  1196.  
  1197. #       ifdef sun3
  1198.     return SYS_SUN3;
  1199. #       endif sun3
  1200.  
  1201. #    ifdef sun4
  1202.     return SYS_SUN4;
  1203. #    endif sun4
  1204. }
  1205.  
  1206. /*
  1207.  * ----------------------------------------------------------------------------
  1208.  *
  1209.  *  Mach_CheckSpecialHandling--
  1210.  *
  1211.  *    Forces a processor to check the special handling flag of a process.
  1212.  *    This should only be called on a multiprocessor.
  1213.  *
  1214.  * Results:
  1215.  *    None.
  1216.  *
  1217.  * Side effects:
  1218.  *    None.
  1219.  *
  1220.  * ----------------------------------------------------------------------------
  1221.  */
  1222. void
  1223. Mach_CheckSpecialHandling(pnum)
  1224.     int        pnum;        /* Processor number. */
  1225. {
  1226.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1227. }
  1228.  
  1229.  
  1230. /*
  1231.  *----------------------------------------------------------------------
  1232.  *
  1233.  * Mach_GetNumProcessors() --
  1234.  *
  1235.  *    Return the number of processors in the system.  NOTE: This should
  1236.  *    really be in a machine-independent area of the mach module.  Note
  1237.  *    further: if this is used only as a system call, it should return
  1238.  *    a ReturnStatus!
  1239.  *
  1240.  * Results:
  1241.  *    The number of processors is returned.  
  1242.  *
  1243.  * Side effects:
  1244.  *    None
  1245.  *
  1246.  *----------------------------------------------------------------------
  1247.  */
  1248.  
  1249. int
  1250. Mach_GetNumProcessors()
  1251. {
  1252.     return (mach_NumProcessors);
  1253. }
  1254.  
  1255.  
  1256.  
  1257. /*
  1258.  *----------------------------------------------------------------------
  1259.  *
  1260.  * MachPageFault() -
  1261.  *
  1262.  *    Handle a page fault.
  1263.  *
  1264.  * Results:
  1265.  *    None
  1266.  *
  1267.  * Side effects:
  1268.  *    A page causing a memory access error is made valid.  If it's an
  1269.  *    illegal page fault in the kernel, we will call panic.
  1270.  *
  1271.  *----------------------------------------------------------------------
  1272.  */
  1273. void
  1274. MachPageFault(busErrorReg, addrErrorReg, trapPsr, pcValue)
  1275.     unsigned    int    busErrorReg;
  1276.     Address        addrErrorReg;
  1277.     unsigned    int    trapPsr;
  1278.     Address        pcValue;
  1279. {
  1280.     Proc_ControlBlock    *procPtr;
  1281.     Boolean        protError;
  1282.     Boolean        copyInProgress = FALSE;
  1283.     ReturnStatus    status;
  1284.     extern        int    VmMachQuickNDirtyCopy();
  1285.     extern        int    VmMachEndQuickCopy();
  1286.  
  1287.     /*
  1288.      * Are we in quick cross-context copy routine?  If so, we can't page fault
  1289.      * in it.
  1290.      */
  1291.     if ((pcValue >= (Address) VmMachQuickNDirtyCopy) &&
  1292.         (pcValue < (Address) VmMachEndQuickCopy)) {
  1293.     /*
  1294.      * This doesn't return to here.  It erases the fact that the
  1295.      * page fault happened and makes the copy routine that
  1296.      * got the page fault return FAILURE to its caller.  We must turn off
  1297.      * interrupts before calling MachHandleBadQuickCopy().
  1298.      */
  1299.     Mach_DisableIntr();
  1300.     MachHandleBadQuickCopy();
  1301.     Mach_EnableIntr();
  1302.     }
  1303.     /*
  1304.      * Are we poking at or peeking into memory-mapped devices?
  1305.      * We must check this before looking for the current process, since this
  1306.      * can happen during boot-time before we have set up processes.
  1307.      */
  1308.     if ((pcValue >= (Address) MachProbeStart)  &&
  1309.         (pcValue < (Address) MachProbeEnd)) {
  1310.     /*
  1311.      * This doesn't return to here.  It erases the fact that the
  1312.      * page fault happened and makes the probe routine that
  1313.      * got the page fault return FAILURE to its caller.  We must turn off
  1314.      * interrupts before calling MachHandleBadProbe().
  1315.      */
  1316.     Mach_DisableIntr();
  1317.     MachHandleBadProbe();
  1318.     Mach_EnableIntr();
  1319.     }
  1320. #ifdef sun4
  1321.     /*
  1322.      * On the sun4/200 with the Jaguar HBA we get VME timeout errors from 
  1323.      * the board. This code retries the error up to 100000 times before droping
  1324.      * into the code below which panics. 
  1325.      * These errors happen a lot with the RAID HPPI boards, so we disable
  1326.      * the printout.
  1327.      */
  1328.     {
  1329.     static timeoutRetryCount = 0;
  1330.     extern void MachVectoredInterruptLoad();
  1331.  
  1332.     if ((trapPsr & MACH_PS_BIT) && (busErrorReg&MACH_TIMEOUT_ERROR)) {
  1333.         /*
  1334.          * If the error occurred on a the load of the interrupt
  1335.          * vector make the routine return.
  1336.          */
  1337.         if (pcValue == (Address) MachVectoredInterruptLoad) {
  1338.         /*
  1339.          * This doesn't return to here.  It erases the fact that the
  1340.          * page fault happened and makes the MachVectoredInterrupt
  1341.          * routine that got the page fault return FAILURE 
  1342.          * to its caller.  
  1343.          */
  1344.         Mach_MonPrintf(
  1345. "MachPageFault: Bus timeout error on VME interrupt vector load pc:0x%x, addr:0x%x\n",
  1346.              pcValue, addrErrorReg);
  1347.         MachHandleBadQuickCopy();
  1348.         }
  1349. #if 0
  1350.         Mach_MonPrintf(
  1351.  "MachPageFault: Bus timeout error retry %d at pc:0x%x, addr:0x%x\n",
  1352.             timeoutRetryCount, pcValue, addrErrorReg);
  1353. #endif
  1354.         if (timeoutRetryCount < 1000000) {
  1355.         timeoutRetryCount++;
  1356.         return;
  1357.         }
  1358.     }
  1359.     timeoutRetryCount = 0;
  1360.     }
  1361.     /* We used to enable interrupts before we called this routine, but we
  1362.      * don't want them enabled if it is a VME bus timeout, so we enable them
  1363.      * now */
  1364.     Mach_EnableIntr();
  1365. #endif /* sun4 */
  1366.  
  1367.     procPtr = Proc_GetActualProc();
  1368.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1369.     panic(
  1370.     "MachPageFault: Current process is NIL!!  Trap pc is 0x%x, addr 0x%x\n",
  1371.         (unsigned) pcValue, addrErrorReg);
  1372.     }
  1373.     /* process kernel page fault */
  1374.     if (trapPsr & MACH_PS_BIT) {        /* kernel mode before trap */
  1375.     if (!(procPtr->genFlags & PROC_USER)) {
  1376.         /*
  1377.          * This fault happened inside the kernel and it wasn't on behalf
  1378.          * of a user process.  This is an error.
  1379.          */
  1380.         panic(
  1381. "MachPageFault: page fault in kernel process! pc:0x%x, addr:0x%x, Error:0x%x\n",
  1382.             pcValue, addrErrorReg, busErrorReg);
  1383.     }
  1384.     /*
  1385.      * A page fault on a user process while executing in
  1386.      * the kernel.  This can happen when information is
  1387.      * being copied back and forth between kernel and user state
  1388.      * (indicated by particular values of the program counter).
  1389.      */
  1390.     if ((pcValue >= (Address) Vm_CopyIn) &&
  1391.         (pcValue < (Address) VmMachCopyEnd)) {
  1392.         copyInProgress = TRUE;
  1393.     } else if ((pcValue >= (Address) MachFetchArgs) &&
  1394.         (pcValue <= (Address) MachFetchArgsEnd)) {
  1395.         copyInProgress = TRUE;
  1396.     } else if (procPtr->vmPtr->numMakeAcc == 0) {
  1397.         /*
  1398.          * ERROR: pc faulted in a bad place!
  1399.          */
  1400.         panic(
  1401.         "MachPageFault: kernel page fault at illegal pc: 0x%x, addr 0x%x\n",
  1402.             pcValue, addrErrorReg);
  1403.     }
  1404.     protError = (busErrorReg & MACH_PROT_ERROR);
  1405.     /*
  1406.      * Try to fault in the page.
  1407.      */
  1408.     status = Vm_PageIn(addrErrorReg, protError);
  1409.     if (status != SUCCESS) {
  1410.         if (copyInProgress) {
  1411.         /*
  1412.          * This doesn't return to here.  It erases the fact that the
  1413.          * page fault happened and makes the copy routine that
  1414.          * got the page fault return SYS_ARG_NO_ACCESS to its caller.
  1415.          * We must turn off interrupts before calling
  1416.          * MachHandleBadArgs().
  1417.          */
  1418.         Mach_DisableIntr();
  1419.         MachHandleBadArgs();
  1420.         Mach_EnableIntr();
  1421.         } else {
  1422.         /* kernel error */
  1423.         panic(
  1424.         "MachPageFault: couldn't page in kernel page at 0x%x, pc 0x%x\n",
  1425.             addrErrorReg, pcValue);
  1426.         }
  1427.     }
  1428.     return;
  1429.     }
  1430.     /* user page fault */
  1431.     protError = busErrorReg & MACH_PROT_ERROR;
  1432.     if (Vm_PageIn(addrErrorReg, protError) != SUCCESS) {
  1433.     printf(
  1434.     "MachPageFault: Bus error in user proc %x, PC = %x, addr = %x BR Reg %x\n",
  1435. #ifdef sun4c
  1436.         procPtr->processID, pcValue, addrErrorReg, busErrorReg);
  1437. #else
  1438.         procPtr->processID, pcValue, addrErrorReg, (short) busErrorReg);
  1439. #endif
  1440.     /* Kill user process */
  1441.     Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, procPtr->processID, FALSE,
  1442.            (Address)addrErrorReg);
  1443.     return;
  1444.     }
  1445.     return;
  1446. }
  1447.  
  1448.  
  1449. /*
  1450.  *----------------------------------------------------------------------
  1451.  *
  1452.  * MachUserAction() -
  1453.  *
  1454.  *    Check what sort of user-process action is needed.  We already know
  1455.  *    that some sort of action is needed, since the specialHandling flag
  1456.  *    should be checked before calling this routine.  The possible actions
  1457.  *    are to take a context switch, to push saved user windows from the mach
  1458.  *    state structure out to the user stack, or to set things up to handle
  1459.  *    pending signals.  We assume traps are enabled before this routine is
  1460.  *    called.
  1461.  *
  1462.  * Results:
  1463.  *    The return value 0 indicates we have no pending signal.
  1464.  *    The return value 1 indicates we have a pending Sprite signal.
  1465.  *    The return value 2 indicates we have a pending Unix signal.
  1466.  *
  1467.  * Side effects:
  1468.  *    The mach state structure may change, especially the mask that indicates
  1469.  *    which windows were saved into the internal buffer.
  1470.  *
  1471.  *----------------------------------------------------------------------
  1472.  */
  1473. int
  1474. MachUserAction()
  1475. {
  1476.     Proc_ControlBlock    *procPtr;
  1477.     Mach_State        *machStatePtr;
  1478.     Sig_Stack        *sigStackPtr;
  1479.     Address        pc;
  1480.     int            unixSignal;
  1481.     int            restarted=0;
  1482.  
  1483.     procPtr = Proc_GetCurrentProc();
  1484.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1485.             procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1486.         printf("UnixProgress = %d entering MachUserReturn\n",
  1487.         procPtr->unixProgress);
  1488.     }
  1489.  
  1490. HandleItAgain:
  1491.     if (procPtr->Prof_Scale != 0 && procPtr->Prof_PC != 0) {
  1492.     Prof_RecordPC(procPtr);
  1493.     }
  1494.     procPtr->specialHandling = 0;
  1495.     /*
  1496.      * Take a context switch if one is pending for this process.
  1497.      * If other stuff, such as flushing the windows to the stack needs to
  1498.      * be done, it will happen when the process is switched back in again.
  1499.      * We came from MachReturnFromTrap, where interrupts were off, so we
  1500.      * must turn them on.
  1501.      */
  1502.     Mach_EnableIntr();
  1503.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1504.     Sched_LockAndSwitch();
  1505.     }
  1506.  
  1507.     machStatePtr = procPtr->machStatePtr;
  1508.  
  1509.     /*
  1510.      * Save the windows that were stored in internal buffers to the user stack.
  1511.      * The windows were saved to internal buffers due to the user stack not
  1512.      * being resident.  The overflow handler can't take page faults, but
  1513.      * we can.
  1514.      */
  1515.     if (machStatePtr->savedMask != 0) {
  1516.     int    i;
  1517.  
  1518.     for (i = 0; i < MACH_NUM_WINDOWS; i++) {
  1519.         if ((1 << i) & machStatePtr->savedMask) {
  1520.         /*
  1521.          * Clear the mask for this window.  We must turn off interrupts
  1522.          * to do this, since changing the savedMask must be an
  1523.          * atomic operation.  If it weren't, and an interrupt came
  1524.          * in that caused us to save some other window to the stack
  1525.          * after we have read the savedMask, we would overwrite the
  1526.          * fact when storing the saved Mask...
  1527.          */
  1528.         Mach_DisableIntr();
  1529.         machStatePtr->savedMask &= ~(1 << i);
  1530.         Mach_EnableIntr();
  1531.         /*
  1532.          * Push the window to the stack.
  1533.          */ 
  1534.         if (Vm_CopyOut(MACH_SAVED_WINDOW_SIZE,
  1535.             (Address)(machStatePtr->savedRegs[i]),
  1536.             (Address)(machStatePtr->savedSps[i])) != SUCCESS) {
  1537.             printf("MachUserAction: pid 0x%x being killed: %s 0x%x.\n",
  1538.                 procPtr->processID, "bad stack pointer?",
  1539.                 machStatePtr->savedSps[i]);
  1540.             Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1541.         }
  1542.         }
  1543.     }
  1544.     }
  1545.     /*
  1546.      * We must check again here to see if the specialHandling flag has been
  1547.      * set again.  We've been taking interrupts this whole time, and the
  1548.      * Vm code above may have called deeply, so we may have saved further
  1549.      * user windows to internal buffers.  If we have, go back up to the
  1550.      * beginning of the routine, and do this all again.
  1551.      */
  1552.  
  1553.     /*
  1554.      * For now, we also flush all the windows to make sure the signal-handling
  1555.      * stuff below won't cause us to save windows to internal buffers.  This
  1556.      * is a slow thing to do, but it is currenlty unclear what to do if
  1557.      * the signal handler causes a window to get saved to an internal buffer.
  1558.      * It will have to call some sort of MachUserAction-type routine itself
  1559.      * in that case.
  1560.      */
  1561.     Mach_DisableIntr();
  1562.     Mach_FlushWindowsToStack();
  1563.     if (procPtr->specialHandling != 0) {
  1564.     goto HandleItAgain;
  1565.     }
  1566.     Mach_EnableIntr();
  1567.     /*
  1568.      * Check for floating point problems.
  1569.      */
  1570.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1571.     HandleFPUException(procPtr, machStatePtr);
  1572.     }
  1573.     /*
  1574.      * Now check for signal stuff. We must check again for floating
  1575.      * point exception because the Sig_Handle might do a context switch
  1576.      * during which the excpetion would get posted. 
  1577.      * 
  1578.      * Note: This is really wrong.  We should check for and process 
  1579.      * any floating point exceptions before  handling a signal. 
  1580.      * The problem here is by the time Sig_Handle returns we are
  1581.      * already committed to doing this signal.
  1582.      */
  1583.     sigStackPtr = &(machStatePtr->sigStack);
  1584.     sigStackPtr->contextPtr = &(machStatePtr->sigContext);
  1585.     if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1586.         procPtr->unixProgress > 0) {
  1587.     /*
  1588.      * If we received a normal signal, we want to restart
  1589.      * the system call when we leave.
  1590.      * If we received a migrate signal, we will get here on
  1591.      * the new machine.
  1592.      * We must also ensure that the argument registers are the
  1593.      * same as when we came in.
  1594.      */
  1595.     restarted = 1;
  1596.     if (debugProcStubs) {
  1597.         printf("Restarting system call with progress %d\n",
  1598.             procPtr->unixProgress);
  1599.     }
  1600.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1601.     }
  1602.     if (Sig_Handle(procPtr, sigStackPtr, &pc)) {
  1603.     machStatePtr->sigContext.machContext.pcValue = pc;
  1604.     machStatePtr->sigContext.machContext.trapInst = MACH_SIG_TRAP_INSTR;
  1605.     /* leave interrupts disabled */
  1606.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1607.         HandleFPUException(procPtr, machStatePtr);
  1608.     }
  1609.     Mach_DisableIntr();
  1610.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1611.         /*
  1612.          * We have to build a proper Unix signal stack.
  1613.          */
  1614.         int n[16];
  1615.         struct sigcontext    unixContext;
  1616.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1617.         if (Compat_SpriteSignalToUnix(sigStackPtr->sigNum,
  1618.             &unixSignal) != SUCCESS) {
  1619.         printf("Signal %d invalid in SetupSigHandler\n",
  1620.             sigStackPtr->sigNum);
  1621.         return 0;
  1622.         }
  1623.  
  1624.         if (restarted) {
  1625.         if (debugProcStubs) {
  1626.             printf("Moving PC to restart system call (doing signal\n");
  1627.         }
  1628.         machStatePtr->trapRegs->nextPc = machStatePtr->trapRegs->pc;
  1629.         machStatePtr->trapRegs->pc = machStatePtr->trapRegs->nextPc-4;
  1630.         /*
  1631.          * We need to restore %o0 which got clobbered by
  1632.          * the system call.
  1633.          */
  1634.         machStatePtr->trapRegs->ins[0] = machStatePtr->savedArgI0;
  1635.         }
  1636.  
  1637.         if (debugProcStubs) {
  1638.         printf("Unix signal %d(%d) to %x\n", sigStackPtr->sigNum,
  1639.             unixSignal, procPtr->processID);
  1640.         }
  1641.         sigStackPtr->sigNum = unixSignal;
  1642.         unixContext.sc_onstack = 0;
  1643.         unixContext.sc_mask = machStatePtr->sigContext.oldHoldMask;
  1644.         unixContext.sc_sp = machStatePtr->trapRegs->ins[6];
  1645.         /*
  1646.          * pc and npc are where to continue the interrupted routine.
  1647.          */
  1648.         if (debugProcStubs) {
  1649.         printf("PSR = %x\n", machStatePtr->trapRegs->curPsr);
  1650.         }
  1651.         unixContext.sc_pc = machStatePtr->trapRegs->pc;
  1652.         unixContext.sc_npc = machStatePtr->trapRegs->nextPc;
  1653.         if (debugProcStubs) {
  1654.         printf("trapRegs->pc=%x, trapRegs->npc=%x, context.pcValue=%x\n",
  1655.             machStatePtr->trapRegs->pc, machStatePtr->trapRegs->nextPc,
  1656.             machStatePtr->sigContext.machContext.pcValue);
  1657.         }
  1658.         unixContext.sc_psr = machStatePtr->trapRegs->curPsr;
  1659.         unixContext.sc_g1 = machStatePtr->trapRegs->globals[1];
  1660.         unixContext.sc_o0 = machStatePtr->trapRegs->ins[0];
  1661.         /*
  1662.          * machContext.pcValue is the address of the handler.
  1663.          */
  1664.         machStatePtr->trapRegs->pc = (unsigned int)
  1665.             machStatePtr->sigContext.  machContext.pcValue;
  1666.         machStatePtr->trapRegs->nextPc = (unsigned int)
  1667.             machStatePtr->sigContext.machContext.pcValue+4;
  1668.         if (debugProcStubs) {
  1669.         printf("new pc = %x\n", machStatePtr->trapRegs->nextPc);
  1670.         }
  1671.         /*
  1672.          * Copy the window to the signal stack.
  1673.          */
  1674.         Vm_CopyIn(16*sizeof(int), (Address)unixContext.sc_sp, (Address)n);
  1675.         if (debugProcStubs) {
  1676.         printf("Regs: %x %x %x, %x %x %x\n", n[0], n[1], n[2], n[8],
  1677.             n[9], n[10]);
  1678.         }
  1679.         machStatePtr->trapRegs->ins[6] += MACH_SAVED_WINDOW_SIZE;
  1680.         unixContext.sc_wbcnt = 0;
  1681.         sigStackPtr->contextPtr = (Sig_Context *)
  1682.             (unixContext.sc_sp-sizeof(struct sigcontext));
  1683.         if (Vm_CopyOut(MACH_SAVED_WINDOW_SIZE,
  1684.             (Address)n,
  1685.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1686.                 - 4*sizeof(int) - MACH_SAVED_WINDOW_SIZE) !=
  1687.                 SUCCESS) {
  1688.         return 0;
  1689.         }
  1690.         if (debugProcStubs) {
  1691.         printf("Copied window to %x\n",
  1692.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1693.                 - 4*sizeof(int) - MACH_SAVED_WINDOW_SIZE);
  1694.         }
  1695.         /*
  1696.          * Copy the sigStack and sigContext to the signal window.
  1697.          */
  1698.         if (Vm_CopyOut(4*sizeof(int), (Address)sigStackPtr,
  1699.             (Address)unixContext.sc_sp - sizeof(struct sigcontext)
  1700.                 - 4*sizeof(int)) != SUCCESS) {
  1701.         return 0;
  1702.         }
  1703.         if (Vm_CopyOut(sizeof(struct sigcontext), (Address)&unixContext,
  1704.             (Address)unixContext.sc_sp - sizeof(struct sigcontext))
  1705.                 != SUCCESS) {
  1706.         return 0;
  1707.         }
  1708.         return 2;
  1709.     } else {
  1710.         return 1;
  1711.     }
  1712.     } else {
  1713.     if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1714.                     procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1715.         restarted = 1;
  1716.         if (debugProcStubs) {
  1717.         printf("No signal action, so we restarted call\n");
  1718.         }
  1719.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1720.     } else if (restarted && debugProcStubs) {
  1721.         printf("No signal, yet we restarted system call!\n");
  1722.     }
  1723.     }
  1724.  
  1725.     if (machStatePtr->fpuStatus & MACH_FPU_EXCEPTION_PENDING) {
  1726.     HandleFPUException(procPtr, machStatePtr);
  1727.     }
  1728.     /*
  1729.      * It is possible for Sig_Handle to mask the migration signal
  1730.      * if a process is not in a state where it can be migrated.
  1731.      * As soon as we return to user mode, though, we will allow migration.
  1732.      * Clear the bit anytime something's pending, for simplicity.
  1733.      */
  1734.     if (procPtr->sigPendingMask) {
  1735.     Sig_AllowMigration(procPtr);
  1736.     }
  1737.  
  1738.     if (restarted) {
  1739.     if (debugProcStubs) {
  1740.         printf("Moving PC to restart system call (no signal\n");
  1741.     }
  1742.     machStatePtr->trapRegs->nextPc = machStatePtr->trapRegs->pc;
  1743.     machStatePtr->trapRegs->pc = machStatePtr->trapRegs->nextPc-4;
  1744.     /*
  1745.      * We need to restore %o0 which got clobbered by
  1746.      * the system call.
  1747.      */
  1748.     machStatePtr->trapRegs->ins[0] = machStatePtr->savedArgI0;
  1749.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1750.     }
  1751.  
  1752.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1753.             procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1754.         printf("UnixProgress = %d leaving MachUserReturn\n",
  1755.         procPtr->unixProgress);
  1756.     }
  1757.  
  1758.     /*
  1759.      * Go back to MachReturnFromTrap.  We are expected to have interrupts
  1760.      * off there.
  1761.      */
  1762.     Mach_DisableIntr();
  1763.     
  1764.     return 0;
  1765. }
  1766.  
  1767.  
  1768. /*
  1769.  *----------------------------------------------------------------------
  1770.  *
  1771.  * MachHandleTrap --
  1772.  *
  1773.  *    Handle an instruction trap, such as an illegal instruction trap,
  1774.  *    an unaligned address, or a floating point problem.
  1775.  *
  1776.  * Results:
  1777.  *    None.
  1778.  *
  1779.  * Side effects:
  1780.  *    If it occured in the kernel, we panic.  If it occured in a user
  1781.  *    program, we take appropriate signal action.
  1782.  *
  1783.  *----------------------------------------------------------------------
  1784.  */
  1785. void
  1786. MachHandleTrap(trapType, pcValue, trapPsr)
  1787.     int            trapType;
  1788.     Address        pcValue;
  1789.     unsigned    int    trapPsr;
  1790. {
  1791.     Proc_ControlBlock    *procPtr;
  1792.  
  1793.     /*
  1794.      * Find the current process.  If we took a MACH_FP_EXCEP at one of the
  1795.      * marked FPU sync instructions, then we use the process saved
  1796.      * in machFPUSaveProcPtr.
  1797.      */
  1798.     procPtr = ((trapType == MACH_FP_EXCEP) && 
  1799.            (pcValue == (Address) machFPUSyncInst)) ?
  1800.            machFPUSaveProcPtr : Proc_GetCurrentProc();
  1801.     if ((procPtr == (Proc_ControlBlock *) NIL)) {
  1802.         printf("%s: pc = 0x%x, trapType = %d\n",
  1803.         "MachHandleTrap", pcValue, trapType);
  1804.         panic("Current process was NIL!\n");
  1805.     }
  1806.     /*
  1807.      * Handle kernel-mode traps.
  1808.      */
  1809.     if (trapPsr & MACH_PS_BIT) {
  1810.     switch (trapType) {
  1811.     case MACH_ILLEGAL_INSTR:
  1812.         printf("%s %s\n", "MachHandleTrap: illegal",
  1813.             "instruction trap in the kernel!");
  1814.         break;
  1815.     case MACH_PRIV_INSTR:
  1816.         printf("%s %s\n", "MachHandleTrap: privileged",
  1817.             "instruction trap in the kernel!");
  1818.         break;
  1819.     case MACH_MEM_ADDR_ALIGN:
  1820.         printf("%s %s\n", "MachHandleTrap: unaligned",
  1821.             "address trap in the kernel!");
  1822.         break;
  1823.     case MACH_TAG_OVERFLOW:
  1824.         printf("%s %s\n", "MachHandleTrap: tag",
  1825.             "overflow trap in the kernel!");
  1826.         break;
  1827.     case MACH_FP_EXCEP: {
  1828. #ifndef NO_FLOATING_POINT
  1829.         /*
  1830.          * We got a FP execption while running in kernel mode. If this
  1831.          * exception occured at a known location we clear the
  1832.          * exception and mark the Mach_State.
  1833.          */
  1834.         if (pcValue == (Address) machFPUDumpSyncInst) {
  1835.         /*
  1836.          * Already doing a MachFPUDumpState.  Whoever's doing the
  1837.          * dump should check the pending flag and set fpuStatus if
  1838.          * it's set.
  1839.          */
  1840.         procPtr->machStatePtr->fpuStatus |=
  1841.             MACH_FPU_EXCEPTION_PENDING;
  1842.         return;
  1843.         }
  1844.         if (pcValue == (Address) machFPUSyncInst) {
  1845.           MachFPUDumpState(procPtr->machStatePtr->trapRegs);
  1846.           procPtr->machStatePtr->fpuStatus |= 
  1847.               (procPtr->machStatePtr->trapRegs->fsr
  1848.                     & MACH_FSR_TRAP_TYPE_MASK) |
  1849.               MACH_FPU_EXCEPTION_PENDING;
  1850.           procPtr->specialHandling = 1;
  1851.           return;
  1852.         } 
  1853.         printf("%s. ",
  1854.     "MachHandleTrap: FPU exception from kernel process.");
  1855.         break;
  1856. #else /* NO_FLOATING_POINT */
  1857.         printf("Floating point op in kernel code: not supported in this\n");
  1858.         panic("kernel due to copyright reasons.");
  1859. #endif /* NO_FLOATING_POINT */
  1860.     }
  1861.     case MACH_FP_DISABLED:
  1862.         printf("%s %s\n", "MachHandleTrap: fp unit",
  1863.             "disabled trap in the kernel!");
  1864.         break;
  1865.     default:
  1866.         printf("%s %s\n", "MachHandleTrap: hit default",
  1867.             "in case statement - bad trap instruction called us!");
  1868.         break;
  1869.     }
  1870.     panic("%s %s %s %x %s %x\n",
  1871.         "MachHandleTrap: the error occured in a",
  1872.         procPtr->genFlags & PROC_USER ? "user" : "kernel",
  1873.         "process, with procPtr =", (unsigned int) procPtr,
  1874.         "and pc =", pcValue);
  1875.     }
  1876.     /*
  1877.      * The trap occured in user-mode.
  1878.      */
  1879.     switch (trapType) {
  1880.     case MACH_ILLEGAL_INSTR:
  1881.     (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE, procPtr->processID,
  1882.         FALSE, pcValue);
  1883.     break;
  1884.     case MACH_PRIV_INSTR:
  1885.     (void) Sig_Send(SIG_ILL_INST, SIG_PRIV_INST, procPtr->processID,
  1886.         FALSE, pcValue);
  1887.     break;
  1888.     case MACH_MEM_ADDR_ALIGN:
  1889.     (void) Sig_Send(SIG_ADDR_FAULT, SIG_ADDR_ERROR, procPtr->processID,
  1890.         FALSE, (Address)0);
  1891.     break;
  1892.     case MACH_FP_EXCEP: {
  1893.          unsigned int fsr;
  1894.      /*
  1895.       * An FP exception from user mode.  Clear the exception and 
  1896.       * mark it in the Mach_State struct.  
  1897.       * 
  1898.       */
  1899.      MachFPUDumpState(procPtr->machStatePtr->trapRegs);
  1900.      fsr = procPtr->machStatePtr->trapRegs->fsr;
  1901.      if (!(procPtr->machStatePtr->fpuStatus & MACH_FPU_ACTIVE)) {
  1902.          printf(
  1903. "FPU exception from process without MACH_FPU_ACTIVE, fsr = 0x%x\n",fsr);
  1904.      }
  1905.      procPtr->machStatePtr->fpuStatus |= (fsr & MACH_FSR_TRAP_TYPE_MASK) |
  1906.                         MACH_FPU_EXCEPTION_PENDING;
  1907.      procPtr->specialHandling = 1;
  1908.      break;
  1909.     }
  1910.     case MACH_FP_DISABLED: {
  1911.     register Mach_State     *machStatePtr;
  1912.  
  1913.     Mach_FlushWindowsToStack();
  1914.     machStatePtr = procPtr->machStatePtr;
  1915.     /*
  1916.      * Upon a user's first FPU disable trap we initialize and enable
  1917.      * the FPU for him. 
  1918.      */
  1919.     if (machStatePtr->fpuStatus & MACH_FPU_ACTIVE) {
  1920.         panic("Double FPU_DISABLE trap.\n");
  1921.     }
  1922.     machStatePtr->fpuStatus = MACH_FPU_ACTIVE;
  1923.     /*
  1924.      * Enable the FPU in the trap PSR.
  1925.      */
  1926.     machStatePtr->trapRegs->curPsr |= MACH_ENABLE_FPP;
  1927.     /*
  1928.      * Initialize the FPU registers. 
  1929.      */
  1930.     machStatePtr->trapRegs->fsr = 0;
  1931.     bzero((Address) (machStatePtr->trapRegs->fregs), MACH_NUM_FPS*4);
  1932.     MachFPULoadState(machStatePtr->trapRegs);
  1933.     break;
  1934.     }
  1935.     case MACH_TAG_OVERFLOW:
  1936.     panic("%s %s\n", "MachHandleTrap: tag",
  1937.         "overflow trap in user process, but I don't deal with it yet.");
  1938.     break;
  1939.     default:
  1940.     panic("%s %s\n", "MachHandleTrap: hit default",
  1941.         "in case statement - bad trap instruction from user mode.");
  1942.     break;
  1943.  
  1944.     }
  1945.     return;
  1946. }
  1947.  
  1948.  
  1949. /*
  1950.  *----------------------------------------------------------------------
  1951.  *
  1952.  * FlushTheWindows --
  1953.  *
  1954.  *    A recursive C routine that will force window overflows and thereby
  1955.  *    flush the register windows to the stack.
  1956.  *
  1957.  * Results:
  1958.  *    None.
  1959.  *
  1960.  * Side effects:
  1961.  *    The register windows are flushed.
  1962.  *
  1963.  *----------------------------------------------------------------------
  1964.  */
  1965. static void
  1966. FlushTheWindows(num)
  1967.     int    num; 
  1968. {
  1969.     num--;
  1970.     if (num > 0) {
  1971.     FlushTheWindows(num);
  1972.     }
  1973.     return;
  1974. }
  1975.  
  1976.  
  1977. /*
  1978.  *----------------------------------------------------------------------
  1979.  *
  1980.  * Mach_FlushWindowsToStack --
  1981.  *
  1982.  *    Calls a routine to flush the register windows to the stack.
  1983.  *    This routine can be caled from traps, or wherever.
  1984.  *
  1985.  * Results:
  1986.  *    None.
  1987.  *
  1988.  * Side effects:
  1989.  *    The register windows are flushed.
  1990.  *
  1991.  *----------------------------------------------------------------------
  1992.  */
  1993. void
  1994. Mach_FlushWindowsToStack()
  1995. {
  1996.     /*
  1997.      * We want to do NWINDOWS - 1 saves and then restores to make sure all our
  1998.      * register windows have been saved to the stack.  Calling here does one
  1999.      * save, so we want to do NWINDOWS - 2 more calls and returns.
  2000.      */
  2001.     FlushTheWindows(MACH_NUM_WINDOWS - 2);
  2002.     return;
  2003. }
  2004.  
  2005.  
  2006. /*
  2007.  *----------------------------------------------------------------------
  2008.  *
  2009.  * MachUserDebug --
  2010.  *
  2011.  *    This will cause the current process to go into the debugger.  It can
  2012.  *    be called from trap handlers, etc.  It first checks to see if the
  2013.  *    current process is NIL.
  2014.  *
  2015.  * Results:
  2016.  *    None.
  2017.  *
  2018.  * Side effects:
  2019.  *    The process gets a breakpoint signal.
  2020.  *
  2021.  *----------------------------------------------------------------------
  2022.  */
  2023. void
  2024. MachUserDebug()
  2025. {
  2026.     Proc_ControlBlock    *procPtr; 
  2027.  
  2028.     procPtr = Proc_GetCurrentProc();
  2029.     if (procPtr == (Proc_ControlBlock *) NIL) {
  2030.     panic("MachUserDebug: current process was NIL!\n");
  2031.     }
  2032.     Sig_Send(SIG_BREAKPOINT, SIG_NO_CODE, procPtr->processID, FALSE,
  2033.         (Address)0);
  2034.     return;
  2035. }
  2036.  
  2037.  
  2038. /*
  2039.  *----------------------------------------------------------------------
  2040.  *
  2041.  * Mach_GetBootArgs --
  2042.  *
  2043.  *    Returns the arguments out of the boot parameter structure. 
  2044.  *
  2045.  * Results:
  2046.  *    Number of elements returned in argv.
  2047.  *
  2048.  * Side effects:
  2049.  *    None.
  2050.  *
  2051.  *----------------------------------------------------------------------
  2052.  */
  2053.  
  2054. int
  2055. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  2056.     int    argc;            /* Number of elements in argv */
  2057.     int    bufferSize;        /* Size of buffer */
  2058.     char    **argv;            /* Ptr to array of arg pointers */
  2059.     char    *buffer;        /* Storage for arguments */
  2060. {
  2061. #ifdef sun4c
  2062.     if (romVectorPtr->v_romvec_version < 2) {
  2063. #endif
  2064.     int        i;
  2065.     int        offset;
  2066.     bcopy(machMonBootParam.strings, buffer, 
  2067.           (bufferSize < 100) ? bufferSize : 100);
  2068.     offset = (unsigned int) machMonBootParam.strings -(unsigned int) buffer;
  2069.     for(i = 0; i < argc; i++) {
  2070.         if (machMonBootParam.argPtr[i] == (char *) 0 ||
  2071.         machMonBootParam.argPtr[i] == (char *) NIL) {
  2072.         break;
  2073.         }
  2074.         argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  2075.     }
  2076.     return i;
  2077. #ifdef sun4c
  2078.     } else {
  2079.     char    *bufEndPtr = buffer + bufferSize - 1;
  2080.     char    *bufferPtr = buffer;
  2081.     int    argcsLeft = argc;
  2082.     char    *p;
  2083.  
  2084.     /*
  2085.      * On version 2 and greater the bootstring is stored in 
  2086.      * two null terminated strings.  We copy these strings
  2087.      * into the argc,argv format needed by Mach_GetBootArgs.
  2088.      */
  2089.     if (argc == 0) {
  2090.         return 0;
  2091.     }
  2092.     p = *(romVectorPtr->bootpath);
  2093.     while (*p && isspace(*p)) { /* Skip any spaces. */
  2094.         p++;
  2095.     }
  2096.     *argv = bufferPtr;
  2097.     argv++; argcsLeft--;
  2098.     while (*p && (bufferPtr < bufEndPtr)) {
  2099.         *bufferPtr++ = *p++;
  2100.     }
  2101.     *bufferPtr++ = 0;
  2102.  
  2103.     p = *(romVectorPtr->bootargs);
  2104.     while (*p && isspace(*p)) {  /* Skip any spaces. */
  2105.         p++;
  2106.     }
  2107.     while ((bufferPtr < bufEndPtr) && (argcsLeft > 0) && *p) {
  2108.         *argv = bufferPtr;
  2109.         argv++; argcsLeft--;
  2110.         while (*p && !isspace(*p) && (bufferPtr < bufEndPtr)) {
  2111.         *bufferPtr++ = *p++;
  2112.         }
  2113.         *bufferPtr++ = 0;
  2114.         while (*p && isspace(*p)) {  /* Skip any spaces. */
  2115.         p++;
  2116.         }
  2117.         }
  2118.     return argc - argcsLeft;
  2119.     }
  2120. #endif /* sun4c */
  2121. }
  2122.  
  2123.  
  2124. /*
  2125.  *----------------------------------------------------------------------
  2126.  *
  2127.  * Mach_GetStackPointer --
  2128.  *
  2129.  *    This is a stub routine for the sun4.
  2130.  *
  2131.  * Results:
  2132.  *    Address.
  2133.  *
  2134.  * Side effects:
  2135.  *    It panics since it should never be called.  If it ends up being
  2136.  *    useful someday, change it so it doesn't panic.
  2137.  *
  2138.  *----------------------------------------------------------------------
  2139.  */
  2140. Address
  2141. Mach_GetStackPointer()
  2142. {
  2143.     panic("Mach_GetStackPointer");
  2144.     return NULL;
  2145. }
  2146.  
  2147. /*
  2148.  *----------------------------------------------------------------------
  2149.  *
  2150.  * HandleFPUException --
  2151.  *
  2152.  *    Handle any FPU exception present.
  2153.  *
  2154.  * Results:
  2155.  *    None.
  2156.  *
  2157.  * Side effects:
  2158.  *    FPU instruction emulated, process may be sent signal.
  2159.  *
  2160.  *----------------------------------------------------------------------
  2161.  */
  2162.  
  2163. static void
  2164. HandleFPUException(procPtr, machStatePtr)
  2165.     Proc_ControlBlock *procPtr;    /* Process control block of offending process*/
  2166.     Mach_State     *machStatePtr;  /* Machine state of process. */
  2167. {    
  2168.     int        i;
  2169.     Mach_RegWindow    *curWindow;
  2170.  
  2171.     switch ((int) (machStatePtr->fpuStatus & MACH_FSR_TRAP_TYPE_MASK)) {
  2172.     case    MACH_FSR_IEEE_TRAP:
  2173.     case    MACH_FSR_UNFINISH_TRAP:
  2174.     case    MACH_FSR_UNIMPLEMENT_TRAP:
  2175.         break;
  2176.     case    MACH_FSR_SEQ_ERRROR_TRAP: {
  2177.         panic("Floating point sequence error, fsr = 0x%x\n",
  2178.          machStatePtr->trapRegs->fsr);
  2179.         break;
  2180.     }
  2181.     case    MACH_FSR_NO_TRAP:
  2182.     default: {
  2183.         panic("Floating point exception with bad trap code, fsr = 0x%x\n", 
  2184.             machStatePtr->trapRegs->fsr);
  2185.         break;
  2186.     }
  2187.     }
  2188.     machStatePtr->fpuStatus &= 
  2189.         ~(MACH_FPU_EXCEPTION_PENDING|MACH_FSR_TRAP_TYPE_MASK);
  2190.     /*
  2191.      * Emulate the evil instructions, and restore the result into the FPU.
  2192.      */
  2193.     curWindow = (Mach_RegWindow *)
  2194.         (machStatePtr->trapRegs->ins[MACH_FP_REG]);
  2195.     for (i = 0; i < machStatePtr->trapRegs->numQueueEntries; i++) {
  2196. #ifndef NO_FLOATING_POINT
  2197.     MachFPU_Emulate(procPtr->processID, 
  2198.             machStatePtr->trapRegs->fqueue[i].address,
  2199.             machStatePtr->trapRegs,
  2200.             curWindow);
  2201. #else /* NO_FLOATING_POINT */
  2202.     printf(
  2203.     "Cannot emulate floating point operations in this kernel version\n");
  2204.     printf("Killing process 0x%x\n", procPtr->processID);
  2205.     (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE, procPtr->processID,
  2206.             FALSE, machStatePtr->trapRegs->pc);
  2207. #endif /* NO_FLOATING_POINT */
  2208.     }
  2209.     MachFPULoadState(machStatePtr->trapRegs);
  2210. }
  2211.  
  2212.  
  2213. /*
  2214.  *----------------------------------------------------------------------
  2215.  *
  2216.  * Mach_SigreturnStub --
  2217.  *
  2218.  *    Return from a unix signal or long jump.
  2219.  *
  2220.  * Results:
  2221.  *    None.
  2222.  *
  2223.  * Side effects:
  2224.  *    Changes control of execution.
  2225.  *
  2226.  *----------------------------------------------------------------------
  2227.  */
  2228. int
  2229. Mach_SigreturnStub(jmpBuf)
  2230. jmp_buf *jmpBuf;
  2231. {
  2232.     struct sigcontext context;
  2233.     Proc_ControlBlock    *procPtr = Proc_GetCurrentProc();
  2234.     Mach_State        *machStatePtr = procPtr->machStatePtr;
  2235.  
  2236.     if (Vm_CopyIn(9*sizeof(int), (Address)jmpBuf, (Address)&context) !=
  2237.         SUCCESS) {
  2238.     printf("jmp_buf copy in failure\n");
  2239.     return -1;
  2240.     }
  2241.     if (debugProcStubs) {
  2242.     printf("Unix sigreturn: pc = %x, sp = %x, psr = %x\n", context.sc_pc,
  2243.         context.sc_sp, context.sc_psr&MACH_DISABLE_TRAP_BIT &
  2244.         ~MACH_PS_BIT);
  2245.     }
  2246.  
  2247.     /*
  2248.      * Flush register windows to stack and maybe our problems will go away.
  2249.      */
  2250.     Mach_DisableIntr();
  2251.     Mach_FlushWindowsToStack();
  2252.     Mach_EnableIntr();
  2253.  
  2254.     machStatePtr->trapRegs->pc = context.sc_pc;
  2255.     machStatePtr->trapRegs->nextPc = context.sc_npc;
  2256.  
  2257.     machStatePtr->trapRegs->globals[1] = context.sc_g1;
  2258.     machStatePtr->trapRegs->ins[0] = context.sc_o0;
  2259.     machStatePtr->sigContext.oldHoldMask = context.sc_mask;
  2260.     machStatePtr->trapRegs->curPsr = (machStatePtr->trapRegs->curPsr&
  2261.         ~MACH_PSR_SIG_RESTORE) | (context.sc_psr&MACH_PSR_SIG_RESTORE);
  2262.     machStatePtr->trapRegs->ins[6] = context.sc_sp;
  2263.     Sig_Return(procPtr, &machStatePtr->sigStack);
  2264.     return 0; /* Dummy */
  2265. }
  2266.  
  2267.  
  2268. /*
  2269.  *----------------------------------------------------------------------
  2270.  *
  2271.  * Mach_FastBoot --
  2272.  *
  2273.  *    Do a fast reboot (using copied initialized heap data, etc.)
  2274.  *
  2275.  * Results:
  2276.  *    FAILURE if we're not set up to do a fast boot.  Otherwise, we don't
  2277.  *    return, but boot instead.
  2278.  *
  2279.  * Side effects:
  2280.  *    Will probably cause fast reboot.
  2281.  *
  2282.  *----------------------------------------------------------------------
  2283.  */
  2284. ReturnStatus
  2285. Mach_FastBoot()
  2286. {
  2287.     if (!recov_DoInitDataCopy) {
  2288.     printf("Can fast reboot: initialized data wasn't copied.");
  2289.     return FAILURE;
  2290.     }
  2291.     MachDoFastBoot();
  2292.     return FAILURE;        /* Should never get here. */
  2293. }
  2294.  
  2295.  
  2296. /*
  2297.  *----------------------------------------------------------------------
  2298.  *
  2299.  * Mach_GetMachineType --
  2300.  *
  2301.  *    Get the machine type from the idprom.
  2302.  *
  2303.  * Results:
  2304.  *    The machine type.
  2305.  *
  2306.  * Side effects:
  2307.  *    Reads from PROM the first time.
  2308.  *
  2309.  *----------------------------------------------------------------------
  2310.  */
  2311. #ifdef sun4c
  2312. int
  2313. Mach_GetMachineType()
  2314. {
  2315.     if (machIdProm.id_format != IDFORM_1) {
  2316.     if (Mach_MonSearchProm("*", "idprom", (char *)&machIdProm,
  2317.         sizeof machIdProm) != sizeof machIdProm) {
  2318.         panic("Where is the idprom?");
  2319.     }
  2320.     }
  2321.     return machIdProm.id_machine;
  2322. }
  2323. #endif /* sun4c */
  2324.  
  2325. /*
  2326.  *----------------------------------------------------------------------
  2327.  *
  2328.  * Mach_GetEtherAddress --
  2329.  *
  2330.  *    Get the ethernet address.
  2331.  *
  2332.  * Results:
  2333.  *    A pointer to the ethernet address.
  2334.  *
  2335.  * Side effects:
  2336.  *    Reads from PROM the first time.
  2337.  *
  2338.  *----------------------------------------------------------------------
  2339.  */
  2340. #ifdef sun4c
  2341. Net_EtherAddress *
  2342. Mach_GetEtherAddress(etherAddressPtr)
  2343.     Net_EtherAddress *etherAddressPtr;
  2344. {
  2345.     if (machIdProm.id_format != IDFORM_1) {
  2346.     if (Mach_MonSearchProm("*", "idprom", (char *)&machIdProm,
  2347.         sizeof machIdProm) != sizeof machIdProm) {
  2348.         panic("Where is the idprom?");
  2349.     }
  2350.     }
  2351.     bcopy((char *)machIdProm.id_ether, (char *)etherAddressPtr,
  2352.     sizeof(Net_EtherAddress));
  2353.     return etherAddressPtr;    /* which copy should I return? */
  2354. }
  2355. #endif /* sun4c */
  2356.